﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBase.h"
#include "GnufUiCommonDef.h"
#include <QtWidgets/QPushButton>
#include <QtWidgets/QDialog>
#include <QtCore/QPointer>

class QColorDialog;
class QDialogButtonBox;
class QLabel;

namespace gnuf {
    class Pallet;
    class QtColorDialog;
    class QtColorPushButton;
    class Color;
    class Info;

    class QtColorPushuButtonIcon : public QWidget
    {
    public:
        QtColorPushuButtonIcon(QtColorPushButton *);
        virtual ~QtColorPushuButtonIcon();
    protected:
        // Inherits from QPushButton...
        virtual void paintEvent(QPaintEvent *) override;
    private:
        const QtColorPushButton * m_qtColorPushButton;
    };

    class GNUF_BASE_EXPORT QtColorPushButton
        : public QPushButton
    {
        Q_OBJECT
    public:
        enum class EStyle : std::uint8_t
        {
            // Fill the color push button with the color.
            eFill,
            // Show the icon and color value on the color push button
            eIconAndColorValue
        };
        
        explicit QtColorPushButton(
            QWidget * qtParentWidget = nullptr,
            const QColor & color = QColor(),
            bool wantToEditAutomatically = false,
            bool alphaChannelEnabled = false,
            bool smartColorSupported = false,
            bool smartColorEnabled = false,
            QtColorPushButton::EStyle style = QtColorPushButton::EStyle::eIconAndColorValue,
            int iconSize = 16);

        virtual ~QtColorPushButton();

        static std::vector<gnuf::Color> customColors();
        static bool setCustomColors(const std::vector<gnuf::Color>& customColors);

        // Set/Get if the alpha channel enabled.
        void setAlphaChannelEnabled(bool);
        bool isAlphaChannelEnabled() const { return m_alphaChannelEnabled; }

        // Set/Get if the smart color supported.
        void setSmartColorSupported(bool);
        bool isSmartColorSupported() const { return m_smartColorSupported; }

        // Set/Get if the smart color enabled.
        void setSmartColorEnabled(bool);
        bool isSmartColorEnabled() const { return m_smartColorEnabled; }

        void setCustomizedInfoSupported(bool);
        bool isCustomizedInfoSupported() const { return m_customizedInfoSupported; }

        void assignCustomizedInfo(const Info& info);
        const Info * customizedInfo() const;

        void setShowCustomizedInfoButton(bool show) { m_showCustomizedInfoButton = show; }
        bool isShowCustomizedInfoButton() { return m_showCustomizedInfoButton; }

        // Set/Get the style.
        void setStyle(QtColorPushButton::EStyle);
        QtColorPushButton::EStyle style() const { return m_style; }

        // Set/Get the icon size.
        void setIconSize(int);
        int iconSize() const { return m_iconSize; }

        // Set/Get the color value text font.
        void setColorValueFont(const QFont &);

        // Set/Get the color.
        void setColor(const QColor &);
        const QColor & color() const { return m_color; }

        // Show the color editor to edit the color. And return the color.
        const QColor & editColor();

        // Draw the smart color stamp on the QWidget.
        static void drawSmartColorStamp(QPaintDevice *);

        void hide(QtColorDialog *, QDialog::DialogCode);

        QDialog::DialogCode colorDialogCode() const { return m_colorDialogCode; }

    protected:
        // Inherits from QPushButton...
        virtual void paintEvent(QPaintEvent *) override;
        virtual void resizeEvent(QResizeEvent *) override;
        virtual void enterEvent(QEvent*) override;
        virtual void leaveEvent(QEvent*) override;
        QLabel* colorValueLabel() { return m_colorValue; }
    private slots:
        void onClicked(bool);
        
    private:
        void refresh();

        QColor m_color;
        bool m_alphaChannelEnabled;
        bool m_smartColorSupported;
        bool m_smartColorEnabled;
        QtColorPushButton::EStyle m_style;
        int m_iconSize;
        QtColorPushuButtonIcon * m_icon;
        QLabel * m_colorValue;
        gcmp::OwnerPtr< Pallet > m_pallet;
        QDialog::DialogCode m_colorDialogCode;
        bool m_isElided = false;

        // support customized text and icon
        bool m_customizedInfoSupported = false;
        gcmp::OwnerPtr<Info> m_opCustomizedInfo = nullptr;
        bool m_showCustomizedInfoButton = false;
    };

    class QtColorDialog;
    class QtColorDialogButton : public QPushButton
    {
        Q_OBJECT
    public:
        enum EIntention {
            eSmartColor,
            eOK,
            eCancel,
            eCustomized
        };
        explicit QtColorDialogButton(
            const QString &,
            QDialogButtonBox *,
            QtColorDialogButton::EIntention,
            QtColorDialog *);
        virtual ~QtColorDialogButton();
        QtColorDialogButton::EIntention intention() const { return m_intention; }
        QtColorDialog * qtColorDialog() const { return m_qtColorDialog; }
    private:
        const QtColorDialogButton::EIntention m_intention;
        QtColorDialog * m_qtColorDialog;
    };
    
    class QtColorDialog : public QWidget
    {
        Q_OBJECT
    public:
        explicit QtColorDialog(QtColorPushButton *);
        virtual ~QtColorDialog();

        // For Journal.
        bool recordJournal(
            const QtColorDialogButton::EIntention, 
            std::map<std::wstring, std::wstring> &);
        bool replayJournal(const std::map<std::wstring, std::wstring> &);

    protected:
        virtual bool eventFilter(QObject *obj, QEvent *event) override;

    private slots:
        void onClicked(QAbstractButton *);

    private:
        bool onButtonClicked(const QtColorDialogButton::EIntention);

        QPointer<QtColorPushButton> m_qtColorPushButton;
        QColorDialog        * m_qtColorDialog;
    };
}
